#include "AbstractItemProxyModel.h"



#include <QTimer>
#include <QDebug>



AbstractItemProxyModel::AbstractItemProxyModel(QObject *parent) :
    QAbstractProxyModel(parent)
{
}



QModelIndex AbstractItemProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent) || parent.isValid()) return QModelIndex();

    QMapIterator<SourceIndex, ProxyIndex> it(m_indexes);
    while (it.hasNext())
    {
        it.next();
        if (it.value().row() != row || it.value().column() != column) continue;

        return it.value();
    }

    return QModelIndex();
}



QModelIndex AbstractItemProxyModel::parent(const QModelIndex &child) const
{
    Q_UNUSED(child);

    return QModelIndex();
}



int AbstractItemProxyModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid()) return 0;

    int rows = 0;
    int row = -1;
    foreach (const QModelIndex proxy, m_indexes.values())
    {
        if (proxy.row() > row) rows++;

        row = proxy.row();
    }
    return rows;
}



QVariant AbstractItemProxyModel::data(const QModelIndex &proxyIndex, int role) const
{
    SourceIndex source = mapToSource(proxyIndex);
    if (!source.isValid()) return QVariant();

    return source.data(role);
}



bool AbstractItemProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role != Qt::EditRole) return false;

    if (!index.isValid()) return false;

    SourceIndex source = mapToSource(index);
    if (!source.isValid()) return false;

    emit layoutAboutToBeChanged();
    bool ret = sourceModel()->setData(source, value, role);
    emit layoutChanged();

    return ret;
}



QModelIndex AbstractItemProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if (!sourceIndex.isValid()) return QModelIndex();
    return m_indexes.value(sourceIndex);
}



QModelIndex AbstractItemProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if (!proxyIndex.isValid()) return QModelIndex();
    return m_indexes.key(proxyIndex);
}



void AbstractItemProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
    //qDebug() << Q_FUNC_INFO;
    QAbstractProxyModel::setSourceModel(sourceModel);

    remap();

    connect(sourceModel, SIGNAL(layoutChanged()), this, SLOT(remap()));
}



void AbstractItemProxyModel::addMapping(const SourceIndex& source, const ProxyIndex& proxy)
{
    //qDebug() << Q_FUNC_INFO;
    m_indexes.insertMulti(source, proxy);
}



ItemModel* AbstractItemProxyModel::itemModel() const
{
    return dynamic_cast<ItemModel*>(sourceModel());
}



void AbstractItemProxyModel::clear()
{
    emit beginResetModel();

    m_indexes.clear();

    emit endResetModel();
}



